iT邦幫忙

2025 iThome 鐵人賽

DAY 27
0
Modern Web

用 LINE OA 打造中小企業訂單系統:從零開始的 30 天實作紀錄系列 第 27

打通付款關鍵的一步:金流串接初探(以綠界 Sandbox 為例

  • 分享至 

  • xImage
  •  

在一個完整的訂單系統中,「付款」是最關鍵的一步

過去幾天我們實作了「下單 → 通知 → 狀態更新」,但顧客仍需手動付款或到現場結帳。

今天,我們要踏出整合金流 API 的第一步,讓系統能自動建立付款連結,完成線上支付。


為什麼要串接金流?

金流串接讓你的系統具備三大能力:

  1. 顧客端自助付款:顧客可在線上直接付款,不再需要人工確認。

  2. 後台即時回報:付款成功後系統自動更新訂單狀態。

  3. 降低錯誤與時間成本:不需對帳、對金額、對收款人。

目前台灣常見金流平台有:

  • 綠界(ECPay):老牌穩定,API 完整。

  • 藍新(NewebPay):支援多種付款方式。

  • LINE Pay:與 LINE OA 結合方便,但開發門檻較高。

今天我們會用 綠界金流 Sandbox 進行示範(免費測試環境)。


金流串接流程概念圖

讓我們先看一下整體流程,了解系統中資料的流向:

https://ithelp.ithome.com.tw/upload/images/20251011/20178868w7GLaP2H7M.png

這是一個「三段式」流程:

  1. 由系統後端建立交易。

  2. 顧客前端開啟付款頁面。

  3. 金流服務回呼通知結果。


Step 1:建立 .env 金流設定

首先在專案根目錄的 .env 新增 Sandbox 參數(以綠界為例):

ECPAY_MERCHANT_ID=2000132
ECPAY_HASH_KEY=5294y06JbISpM5x9
ECPAY_HASH_IV=v77hoKGq4kWxNNIS
ECPAY_RETURN_URL=https://yourdomain.com/payment/webhook
ECPAY_CLIENT_BACK_URL=https://yourdomain.com/liff-form/success
ECPAY_API_URL=https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5

Sandbox 的 MerchantID 固定是 2000132,HashKey 與 HashIV 為官方提供的測試值。


Step 2:建立付款 API

新增路由 routes/payment.js

const express = require("express");
const router = express.Router();
const crypto = require("crypto");
const querystring = require("querystring");

router.post("/create", async (req, res) => {
  const { orderId, amount, itemName } = req.body;
  const tradeNo = `T${Date.now()}`; // 測試用交易編號

  const params = {
    MerchantID: process.env.ECPAY_MERCHANT_ID,
    MerchantTradeNo: tradeNo,
    MerchantTradeDate: new Date().toLocaleString("zh-TW", { hour12: false }),
    PaymentType: "aio",
    TotalAmount: amount,
    TradeDesc: "LINE 訂單付款",
    ItemName: itemName,
    ReturnURL: process.env.ECPAY_RETURN_URL,
    ClientBackURL: process.env.ECPAY_CLIENT_BACK_URL,
    ChoosePayment: "ALL",
  };

  // 組出 CheckMacValue (雜湊驗證)
  const raw = `HashKey=${process.env.ECPAY_HASH_KEY}&${querystring.stringify(params)}&HashIV=${process.env.ECPAY_HASH_IV}`;
  const encoded = encodeURIComponent(raw).toLowerCase().replace(/%20/g, '+');
  const checkMacValue = crypto.createHash("sha256").update(encoded).digest("hex").toUpperCase();

  params.CheckMacValue = checkMacValue;

  const form = `
    <form id="ecpay-form" method="POST" action="${process.env.ECPAY_API_URL}">
      ${Object.entries(params).map(([k, v]) => `<input type="hidden" name="${k}" value="${v}" />`).join("")}
    </form>
    <script>document.getElementById("ecpay-form").submit();</script>
  `;

  res.send(form);
});

module.exports = router;

index.js 引入:

const paymentRoutes = require('./src/routes/payment');
app.use('/payment', paymentRoutes);

這樣前端就能呼叫 /payment/create 拿到自動送出的付款表單。


Step 3:前端觸發付款

在你的 LIFF 或管理頁中,按下「付款」按鈕後:

fetch("/payment/create", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    orderId: "664a21b...",
    amount: 120,
    itemName: "紅茶拿鐵 x2",
  }),
})
  .then((res) => res.text())
  .then((html) => {
    const blob = new Blob([html], { type: "text/html" });
    const url = URL.createObjectURL(blob);
    window.location.href = url;
  });

使用者會被導向綠界 Sandbox 的付款頁面,進行測試交易。


Step 4:觀察綠界回傳(Day 28 前導)

付款後綠界會發送 POST webhook 到你的 /payment/webhook
裡面會包含交易結果、金額、驗證碼等資訊。

範例 payload:

{
  "MerchantID": "2000132",
  "RtnCode": "1",
  "RtnMsg": "交易成功",
  "MerchantTradeNo": "T1728658000000",
  "TradeAmt": "120"
}

下一篇(Day 28)我們將處理這段 webhook,讓系統能自動:

「付款成功 → 訂單狀態改為 Completed → 同時通知顧客與群組」


重點回顧

  • 認識金流串接流程(建立交易 → 導向付款 → 接 webhook)。

  • 建立第一個可運作的綠界 Sandbox 付款 API。

  • 理解 CheckMacValue 驗證與金流安全性的重要性。

  • 為明日的 webhook 實作打好基礎。


明天我們將實作「金流 webhook 整合」,
讓整個流程自動閉環:
付款 → 更新狀態 → Redis Worker 通知 → LINE 推播 💬
真正達成「全自動化訂單系統」的最後拼圖!


上一篇
讓管理者一眼掌握訂單全貌:訂單明細頁 / 後台 Dashboard 優化
下一篇
金流 webhook + 訂單狀態通知整合
系列文
用 LINE OA 打造中小企業訂單系統:從零開始的 30 天實作紀錄30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言